package com.wxapp.common.util.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.wxapp.common.base.util.encryption.EncryptionUtil;
import com.wxapp.common.base.util.md5.Md5Util;
import com.wxapp.common.constant.enums.ResultEnum;
import com.wxapp.common.constant.properties.LoginProperties;
import com.wxapp.common.core.annotation.util.IpUtil;
import com.wxapp.common.core.filter.except.LoginException;
import com.wxapp.common.util.check.CheckUtil;
import com.wxapp.common.util.random.RandomUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * TODO:
 *
 * @Param:
 * @Author: lgl
 * @Date 2023/4/13 11:04
 */
@Component
public class JWTUtil {
    private final LoginProperties loginProperties;
    private final JWTVerifier decodedJWT;

    public JWTUtil(LoginProperties loginProperties) {
        this.loginProperties = loginProperties;
        decodedJWT = JWT.require(Algorithm.HMAC256(loginProperties.getSecret())).build();
    }

    /**
     * 创建TOKEN
     *
     * @param sub
     * @return
     */
    public String createToken(HttpServletRequest request,String sub) {
        return  JWT.create().withSubject(EncryptionUtil.aesEncrypt(Md5Util.md5(IpUtil.getIp(request)), sub))
                .withExpiresAt(new Date(System.currentTimeMillis() + loginProperties.getExpireTime() * 1000))
                .withJWTId(RandomUtil.getUUID())
                .withIssuedAt(new Date())
                .sign(Algorithm.HMAC256(loginProperties.getSecret()));
    }

    /**
     * 验证token
     *
     * @param token
     */
    public Boolean validateToken(HttpServletRequest request,String token) throws LoginException {
        try {
            var verify = decodedJWT.verify(token);
            if (verify.getSubject() != null && !"".equals(verify.getSubject()) && (verify.getExpiresAt().getTime() - System.currentTimeMillis()) < (loginProperties.getExpireTime())){
                return true;
            }
            token = EncryptionUtil.aesDecrypt(Md5Util.md5(IpUtil.getIp(request)), verify.getSubject());
            return CheckUtil.isNotNullString(token);
        } catch (Exception e) {
            throw new LoginException(ResultEnum.REQUEST_TIMEOUT);
        }
    }
}